#include "gameroom.h"
#include "gamehall.h"

#include <QIcon>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QDebug>

GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{
    this->setFixedSize(1000, 800);
    this->setWindowTitle("游戏房间");
    this->setWindowIcon(QIcon(":/res/ico.png"));

    snakeList.push_back(QRectF(800 * 0.5, 800 * 0.5, snakeNodeWidth, snakeNodeHeight));
    moveUp();
    moveUp();

    //生成食物坐标位置
    createFood();

    //设置定时器实现蛇的移动
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [=](){
        int cnt = 1;//每次defautTimeout 往相应的方向移动一个单位长度 等价于往头部相应方向增加一个节点 再将尾节点删除 如果移动过程中吃到食物 则往头部继续添加节点 即至少移动一次
        if (snakeList.front().intersects(foodPos))
        {
            cnt++;
            createFood();
        }
        while (cnt--)
        {
            switch (moveDirection)
            {
            case UP:
                moveUp();
                break;
            case DOWN:
                moveDown();
                break;
            case LEFT:
                moveLeft();
                break;
            case RIGHT:
                moveRight();
                break;
            }
        }
        snakeList.pop_back();
        update();//重新绘制界面
    });

    //开始/结束游戏按钮
    QPushButton* start = new QPushButton(this);
    setButtonAttribute(start, "开始游戏");
    start->move(830, 150);
    connect(start, &QPushButton::clicked, this, [=](){
        isGameStart = true;
        timer->start(moveTimeout);
        sound = new QSound(":/res/Trepak.wav");
        sound->play();
        sound->setLoops(-1);
    });

    QPushButton* stop = new QPushButton(this);
    setButtonAttribute(stop, "暂停游戏");
    stop->move(830, 250);
    connect(stop, &QPushButton::clicked, this, [=](){
        isGameStart = false;
        timer->stop();
        sound->stop();
    });

    QPushButton* exit = new QPushButton(this);
    setButtonAttribute(exit, "退出游戏");
    exit->move(830, 700);
    QMessageBox* message = new QMessageBox(this);
    QPushButton* ok = new QPushButton("ok");
    QPushButton* cancel = new QPushButton("cancel");
    message->addButton(ok, QMessageBox::ButtonRole::AcceptRole);
    message->addButton(cancel, QMessageBox::ButtonRole::RejectRole);
    message->setWindowTitle("退出游戏");
    message->setText("是否要退出游戏?");
    connect(exit, &QPushButton::clicked, this, [=](){
        if (isGameStart)
        {
            timer->stop();
            sound->stop();
            isGameStart = false;
        }
        QSound::play(":/res/clicked.wav");
        message->show();
        message->exec();//模态对话框 在该对话框关闭前 不能对父窗口进行操作
        if (message->clickedButton() == ok)
        {
            GameSelect* gameselect = new GameSelect;
            gameselect->setFixedSize(this->width(), this->height());
            this->close();
            gameselect->show();
        }
        else
        {
            message->close();
        }
    });

    //上下左右方向按钮控制蛇的移动方向
    QPushButton* up = new QPushButton(this);
    up->setFixedSize(50, 50);
    up->move(880, 400);
    up->setCursor(QCursor((Qt::CursorShape::PointingHandCursor)));
    up->setIcon(QIcon(":/res/up_key.png"));
    up->setShortcut(QKeySequence(Qt::Key_W));
    connect(up, &QPushButton::clicked, this, [=](){
       if (moveDirection != DOWN)
           moveDirection = UP;
    });

    QPushButton* down = new QPushButton(this);
    down->setFixedSize(50, 50);
    down->move(880, 500);
    down->setCursor(QCursor((Qt::CursorShape::PointingHandCursor)));
    down->setIcon(QIcon(":/res/down_key.png"));
    down->setShortcut(QKeySequence(Qt::Key_S));
    connect(down, &QPushButton::clicked, this, [=](){
       if (moveDirection != UP)
           moveDirection = DOWN;
    });

    QPushButton* left = new QPushButton(this);
    left->setFixedSize(50, 50);
    left->move(830, 450);
    left->setCursor(QCursor((Qt::CursorShape::PointingHandCursor)));
    left->setIcon(QIcon(":/res/left_key.png"));
    left->setShortcut(QKeySequence(Qt::Key_A));
    connect(left, &QPushButton::clicked, this, [=](){
       if (moveDirection != RIGHT)
           moveDirection = LEFT;
    });

    QPushButton* right = new QPushButton(this);
    right->setFixedSize(50, 50);
    right->move(930, 450);
    right->setCursor(QCursor((Qt::CursorShape::PointingHandCursor)));
    right->setIcon(QIcon(":/res/right_key.png"));
    right->setShortcut(QKeySequence(Qt::Key_D));
    connect(right, &QPushButton::clicked, this, [=](){
       if (moveDirection != LEFT)
           moveDirection = RIGHT;
    });
}

void GameRoom::paintEvent(QPaintEvent *event)
{
    (void)event;
    QPainter painter(this);
    QPixmap pixmap;
    pixmap.load(":/res/game_room.png");
    painter.drawPixmap(0, 0, 800, 800, pixmap);
    pixmap.load(":/res/bg1.png");
    painter.drawPixmap(800, 0, 210, 820, pixmap);

    //绘制蛇头
    auto snakeHead = snakeList.front();
    switch (moveDirection)
    {
    case UP:
        pixmap.load(":/res/up.png");
        painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pixmap);
        break;
    case DOWN:
        pixmap.load(":/res/down.png");
        painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pixmap);
        break;
    case LEFT:
        pixmap.load(":/res/left.png");
        painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pixmap);
        break;
    case RIGHT:
        pixmap.load(":/res/right.png");
        painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pixmap);
        break;
    }

    //绘制蛇身
    for (int i = 1; i < snakeList.size() - 1; i++)
    {
        auto snakeBody = snakeList.at(i);
        pixmap.load(":/res/Bd.png");
        painter.drawPixmap(snakeBody.x(), snakeBody.y(), snakeBody.width(), snakeBody.height(), pixmap);
    }

    //绘制蛇尾
    auto snakeTail = snakeList.back();
    pixmap.load(":/res/Bd.png");
    painter.drawPixmap(snakeTail.x(), snakeTail.y(), snakeTail.width(), snakeTail.height(), pixmap);

    //绘制食物
    pixmap.load(":/res/food.bmp");
    painter.drawPixmap(foodPos.x(), foodPos.y(), foodPos.width(), foodPos.height(), pixmap);

    //绘制分数
    pixmap.load(":/res/score_bg.png");
    painter.drawPixmap(830, 30, 140, 65, pixmap);
    painter.setPen(QPen(Qt::black));
    painter.setFont(QFont("华文行楷", 15));
    painter.drawText(900, 75, QString("%1").arg(snakeList.size() - 3));

    //每次绘制时 如果当前得分高于历史最高得分 将当前得分存放至历史战绩文件
    int currentScore = snakeList.size() - 3;
    QFile file("D:/QTcode/Snake/score.txt");
    file.open(QIODevice::ReadWrite | QIODevice::Text);
    QTextStream ts(&file);
    int historyScore = ts.readLine().toInt();
    if (currentScore > historyScore)
    {
        file.resize(0);
        ts << currentScore;
    }
    file.close();

    //游戏失败时 绘制提示信息
    if (isFailed())
    {
        painter.setPen(QPen(Qt::red));
        painter.setFont(QFont("华文行楷", 50));
        painter.drawText(200, 400, "GAME OVER");
        timer->stop();
        sound->stop();
    }
}

void GameRoom::moveUp()
{
    QRectF snakeNode = snakeList.front();
    if (snakeNode.y() < 0)//向上移动出界
        snakeNode.setY(this->height() - snakeNodeHeight);
    else
        snakeNode.setY(snakeNode.y() - snakeNodeHeight);
    snakeList.push_front(QRect(snakeNode.x(), snakeNode.y(), snakeNodeWidth, snakeNodeHeight));
}

void GameRoom::moveDown()
{
    QRectF snakeNode = snakeList.front();
    if (snakeNode.y() > this->height())//向下移动出界
        snakeNode.setY(0);
    else
        snakeNode.setY(snakeNode.y() + snakeNodeHeight);
    snakeList.push_front(QRect(snakeNode.x(), snakeNode.y(), snakeNodeWidth, snakeNodeHeight));
}

void GameRoom::moveLeft()
{
    QRectF snakeNode = snakeList.front();
    if (snakeNode.x() < 0)//向左移动出界
        snakeNode.setX(800 - snakeNodeWidth);
    else
        snakeNode.setX(snakeNode.x() - snakeNodeWidth);
    snakeList.push_front(QRect(snakeNode.x(), snakeNode.y(), snakeNodeWidth, snakeNodeHeight));
}

void GameRoom::moveRight()
{
    QRectF snakeNode = snakeList.front();
    if (snakeNode.x() > 760)//向右移动出界
        snakeNode.setX(0);
    else
        snakeNode.setX(snakeNode.x() + snakeNodeWidth);
    snakeList.push_front(QRect(snakeNode.x(), snakeNode.y(), snakeNodeWidth, snakeNodeHeight));
}

void GameRoom::createFood()
{
    foodPos = QRectF(qrand() % (800 / snakeNodeWidth) * snakeNodeWidth,
                     qrand() % (800 / snakeNodeHeight) * snakeNodeHeight,
                     snakeNodeWidth, snakeNodeHeight);
}

bool GameRoom::isFailed()
{
    for (int i = 0; i < snakeList.size(); i++)
    {
        for (int j = i + 1; j < snakeList.size(); j++)
        {
            if (snakeList.at(i) == snakeList.at(j))//两个节点坐标重合
                return true;
        }
    }
    return false;
}

void GameRoom::setMoveTimeout(int timeout)
{
    moveTimeout = timeout;
}

void GameRoom::setButtonAttribute(QPushButton *button, const QString &text)
{
    button->setText(text);
    button->setFont(QFont("华文行楷", 15));
    button->setStyleSheet("background: white; padding: 8px 15px; border: 1px solid white; border-radius: 15px");
    button->setCursor(QCursor((Qt::CursorShape::PointingHandCursor)));
}
